﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;


namespace PathFinding
{
    public abstract class PFObstacle
    {
        /// <summary>
        /// 所占据的节点
        /// </summary>
        public List<Vector2Int> Captured { get; protected set; }

        public PFGrid Grid;

        public PFObstacle(PFGrid grid)
        {
            Grid = grid;
        }

        public void UpdateGridPoint()
        {
            foreach (var pos in Captured)
            {
                Grid[pos].Passibility = 0;
            }
        }

        public abstract void DebugDraw(Color color1);
    }

    /// <summary>
    /// 障碍物，范围包括TL到BR，包括TL和BR边界
    /// </summary>
    public class AABBObstacle : PFObstacle
    {
        Vector2Int TL, BR;
        public Vector2Int TopLeft => TL;
        public Vector2Int BottomRight => BR;

        public Vector2 TopLeftWorld => TL * Grid.CellSize;
        public Vector2 BottomRightWorld => BR * Grid.CellSize;

        public AABBObstacle(PFGrid grid, Vector2Int tl, Vector2Int br) : base(grid)
        {
            Captured = new List<Vector2Int>();
            UpdatePos(tl, br);
        }

        /// <summary>
        /// use world tl br
        /// </summary>
        public AABBObstacle(PFGrid grid, Vector2 center, Vector2 halfXYSize) : base(grid)
        {
            Captured = new List<Vector2Int>();
            center /= Grid.CellSize;
            var xsize = MathF.Abs(halfXYSize.x / Grid.CellSize.x);
            var ysize = MathF.Abs(halfXYSize.y / Grid.CellSize.y);
            var tl = new Vector2Int((int)Mathf.Round(center.x - xsize), (int)Mathf.Round(center.y - ysize));
            var br = new Vector2Int((int)Mathf.Round(center.x + xsize), (int)Mathf.Round(center.y + ysize));
            UpdatePos(tl, br);

        }

        public void UpdatePos(Vector2Int tl, Vector2Int br)
        {
#if DEBUG
            if (tl.x > br.x || tl.y > br.y)
                throw new Exception("TL应该在BR的左上方，也可以重叠。");
#endif

            TL = tl;
            BR = br;
            Captured.Clear();
            for (int x = TL.x; x <= BR.x; ++x)
            {
                for (int y = TL.y; y <= BR.y; ++y)
                {
                    if (Grid.HasPointAt(x, y))
                        Captured.Add(new Vector2Int(x, y));
                }
            }
        }


        public void UpdateByWorldPos(Vector2 tl, Vector2 br)
        {
            UpdatePos(new Vector2Int((int)Mathf.Round(tl.x / Grid.CellSize.x), (int)Mathf.Round(tl.y / Grid.CellSize.y)),
                new Vector2Int((int)Mathf.Round(br.x / Grid.CellSize.x), (int)Mathf.Round(br.y / Grid.CellSize.y))
                );
        }



        public override void DebugDraw(Color color1)
        {
            foreach (var p in Captured)
            {
                Debug.DrawLine(new Vector3(p.x * Grid.CellSize.x, 0, p.y * Grid.CellSize.y), new Vector3(p.x * Grid.CellSize.x, 2, p.y * Grid.CellSize.y), color1);
            }
            //Debug.Log(Captured.Count);
            Gizmos.DrawWireCube(new Vector3(TopLeftWorld.x + (BottomRightWorld.x - TopLeftWorld.x) * 0.5f, 0, TopLeftWorld.y + (BottomRightWorld.y - TopLeftWorld.y) * 0.5f),
                new Vector3((BottomRightWorld.x - TopLeftWorld.x) + Grid.CellSize.x * 0.5f, 1, (BottomRightWorld.y - TopLeftWorld.y) + Grid.CellSize.y * 0.5f));
        }

    }
}